/*
 * pg_crc.h
 *
 * PostgreSQL CRC 支持
 *
 * 参阅 Ross Williams 的精彩介绍
 * A PAINLESS GUIDE TO CRC ERROR DETECTION ALGORITHMS， 可从
 * http://ross.net/crc/ 或其他一些网络网站获取。
 *
 * 我们有三种略有不同的 32 位 CRC 计算变体：
 * CRC-32C（Castagnoli 多项式），CRC-32（以太网多项式），以及
 * 一种使用查找表以特殊方式的传统 CRC-32 版本。它们都由四个宏组成：
 *
 * INIT_<variant>(crc)
 *		初始化一个 CRC 累加器
 *
 * COMP_<variant>(crc, data, len)
 *		将一些（更多的）字节累加到 CRC 中
 *
 * FIN_<variant>(crc)
 *		完成 CRC 计算
 *
 * EQ_<variant>(c1, c2)
 *		检查两个 CRC 是否相等。
 *
 * CRC-32C 变体在 port/pg_crc32c.h 中。
 *
 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 * src/include/utils/pg_crc.h
 */
#ifndef PG_CRC_H
#define PG_CRC_H

typedef uint32 pg_crc32;

/*
 * CRC-32，和例如以太网中使用的相同。
 *
 * 这目前仅在 ltree 和 hstore 贡献模块中使用。它使用
 * 与下面的传统算法相同的查找表。新代码应该
 * 使用 Castagnoli 版本。
 */
#define INIT_TRADITIONAL_CRC32(crc) ((crc) = 0xFFFFFFFF)
#define FIN_TRADITIONAL_CRC32(crc)	((crc) ^= 0xFFFFFFFF)
#define COMP_TRADITIONAL_CRC32(crc, data, len)	\
	COMP_CRC32_NORMAL_TABLE(crc, data, len, pg_crc32_table)
#define EQ_TRADITIONAL_CRC32(c1, c2) ((c1) == (c2))

/* Sarwate的算法，用于“正常”查找表 */
#define COMP_CRC32_NORMAL_TABLE(crc, data, len, table)			  \
do {															  \
	const unsigned char *__data = (const unsigned char *) (data); \
	uint32		__len = (len); \
\
	while (__len-- > 0) \
	{ \
		int		__tab_index = ((int) (crc) ^ *__data++) & 0xFF; \
		(crc) = table[__tab_index] ^ ((crc) >> 8); \
	} \
} while (0)

/*
 * 预9.5版本中用于WAL等的CRC算法。
 *
 * 这与正常的CRC-32算法非常相似，但有微妙的不同。使用Williams的术语，我们使用“正常”表，但使用“反射”的代码。这是错误的，但在任何人注意到之前，这种情况持续了多年。它与正常CRC算法中的任何多项式都不对应，因此目前尚不清楚该算法的错误检测特性是什么。
 *
 * 我们仍然需要携带这个，因为它用于一些需要pg可升级的磁盘结构中。它不应在新代码中使用。
 */
#define INIT_LEGACY_CRC32(crc) ((crc) = 0xFFFFFFFF)
#define FIN_LEGACY_CRC32(crc)	((crc) ^= 0xFFFFFFFF)
#define COMP_LEGACY_CRC32(crc, data, len)	\
	COMP_CRC32_REFLECTED_TABLE(crc, data, len, pg_crc32_table)
#define EQ_LEGACY_CRC32(c1, c2) ((c1) == (c2))

/*
 * Sarwate的算法，用于“反射”的查找表（但在传统算法中，我们实际上在“正常”表上使用它，见上文）
 */
#define COMP_CRC32_REFLECTED_TABLE(crc, data, len, table) \
do {															  \
	const unsigned char *__data = (const unsigned char *) (data); \
	uint32		__len = (len); \
\
	while (__len-- > 0) \
	{ \
		int		__tab_index = ((int) ((crc) >> 24) ^ *__data++) & 0xFF; \
		(crc) = table[__tab_index] ^ ((crc) << 8); \
	} \
} while (0)

/*
 * CRC-32多项式的常量表。该表被正常和传统变体共同使用。
 */
extern PGDLLIMPORT const uint32 pg_crc32_table[256];

#endif							/* PG_CRC_H */
